package com.itheima.entry.controller.impl;

import com.itheima.entry.controller.IStudentController;
import com.itheima.entry.controller.ISuperController;
import com.itheima.entry.controller.IUserController;
import com.itheima.entry.domain.UserInfo;
import com.itheima.entry.factory.StudentFactroy;
import com.itheima.entry.factory.SuperFactory;
import com.itheima.entry.factory.UserFactroy;
import com.itheima.entry.service.IUserService;
import com.itheima.utils.email.SendEmail;
import org.apache.poi.ss.formula.functions.DMax;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import java.io.*;
import java.nio.charset.Charset;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Properties;
import java.util.Scanner;

public class UserControllerImpl implements IUserController {

    private Scanner sc = new Scanner(System.in);
    private IStudentController studentController = StudentFactroy.getController();
    private IUserService userService = UserFactroy.getService();
    private ISuperController superController = SuperFactory.getController();
    //记录当前登录的用户
    private UserInfo currentUser = null;
    //2种时间解析格式
    private DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
    private DateTimeFormatter fmtProp = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
    private static Properties propUser = new Properties();
    private static Properties propSuper = new Properties();
    private static Logger logger = LoggerFactory.getLogger("UserControllerImpl2.class");

    static {
        //初始化本地文件夹
        File fileImport = new File("D:\\heima_system\\import");
        File fileExport = new File("D:\\heima_system\\export");
        File fileBackup = new File("D:\\heima_system\\backup");
        File fileLog = new File("D:\\heima_system\\log");
        File fileProp = new File("D:\\heima_system\\prop");
        fileExport.mkdirs();
        fileImport.mkdirs();
        fileBackup.mkdirs();
        fileLog.mkdirs();
        fileProp.mkdirs();
        /*
        载入配置文件中的用户登录信息和管理员登录信息
         */
        FileReader readUser = null;
        FileReader readAdmin = null;
        try {
            readUser = new FileReader("D:\\heima_system\\prop\\userAccess.properties");
            readAdmin = new FileReader("D:\\heima_system\\prop\\superProp.properties");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
//        InputStream ss = ClassLoader.getSystemResourceAsStream("D:\\heima_system\\prop\\userAccess.properties");
//        InputStream ss2 = ClassLoader.getSystemResourceAsStream("D:\\heima_system\\prop\\superProp.properties");
        try {
//            propUser.load(ss);
//            propSuper.load(ss2);

            propUser.load(readUser);
            propSuper.load(readAdmin);
//            System.out.println(prop);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (readUser != null) {
            try {
                readUser.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (readAdmin != null) {
            try {
                readAdmin.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /*
    程序入口菜单
    用户的登录  注册  找回密码  和超级管理员页面入口
     */
    public void entry() {

        System.out.println("==========黑马信息管理系统==========");
        while (true) {
            System.out.println("1.用户登录\t\t 2.注册\t\t3.找回密码\t\t4.超级登录");
            switch (sc.next()) {
                case "1":
//                    System.out.println("请输入登录的用户名和密码");
                    login();
                    break;
                case "2":
//                    System.out.println("注册信息");
                    register();
                    break;
                case "3":
                    System.out.println("通过邮箱找回密码");
                    findPassword();
                    break;
                case "4":
                    System.out.println("超级管理员登录页面");
                    superAdmin();
                    break;

                default:
                    System.out.println("输入有误");
                    break;

            }
        }

    }
    /*
    这里进入超级管理员登录页面
     */
    private void superAdmin() {
        superController.login();
    }


    //管理界面
    public void admin() {
        while (true) {
            System.out.println("1.  学生管理   2.数据管理   3.修改密码  4.退出");
            switch (sc.next()) {
                case "1":
                    System.out.println("进入学生管理");
                    studentController.star();
                    break;
                case "2":
//                    System.out.println("进入数据管理");
                    start();
                    break;
                case "3":
                    System.out.println("进入修改密码页面");
                    ChangePassword();
                    break;
                case "4":
                    System.out.println("谢谢使用,再见");
                    entry();
                default:
                    System.out.println("输入有误");
                    break;
            }
        }
    }

    //数据管理的菜单
    @Override
    public void start() {
        while (true) {
            System.out.println("数据管理: 1  导出信息  2 导入信息 3 返回上一级 4 退出");
            switch (sc.next()) {
                case "1":
                    exportInfo();
                    break;
                case "2":
//                    System.out.println("信息导入成功");
                    importInfo();
                    break;
                case "3":
                    admin();
                    break;
                case "4":
                    System.out.println("谢谢使用,再见");
                    entry();  //保存信息退出
                    break;
                default:
                    System.out.println("输入有误");
                    break;
            }
        }
    }

    //登录成功后显示欢迎信息,记录时间信息
    public void welcome() {
        System.out.println("尊敬的至尊VIP<< " + currentUser.getUsername() + " >>欢迎进入管理系统");
        LocalDateTime exitDate = currentUser.getExitDate();
        if (exitDate != null) {
            String lastData = exitDate.format(fmt);
//            String lastData = currentUser.getLoginDate().format(fmt);
            System.out.println("上次登录时间是:" + lastData); // 打印最后在线的时间
        }

//        System.out.println("记录本次登录的时间");
        currentUser.setLoginDate(LocalDateTime.now());
        admin();//进入选择管理员界面
    }

    /*
    @用户登录并验证
    @先从propUser集合中判断标记,如果标记true就可以直接进行登录;
    @如果标记是false就对次数进行判断,如果次数大于0,就进行登录
    @如果次数=0,就对时间进行判断,如果时间小于锁定时间就拒绝登录
    @否则重置登录次数,并进入登录页面;
     */
    @Override
    public void login() {
        //accessLogin方法对是否允许登录进行判断
        int count = getUserCount();
        boolean access = getAccess();
        long time = timeAccess();

        String  max = propUser.getProperty("max");
        //标记是false就不允许登录   //登录时间小于20秒,也不允许登录
        if (!access) {
            if (count <= 0) {
                if (time < Integer.parseInt(propUser.getProperty("seconds"))) {
                    System.out.println("您因密码输入次数过多,暂时无法登录系统");
                    return;
                } else {
                    propUser.setProperty("count", max);//重置登录次数
                    try {

                        propUser.store(new FileWriter("D:\\heima_system\\prop\\userAccess.properties", Charset.forName("gbk")), null);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

            }
        }
        /*
        @用户名密码如果正确就进入系统
        @如果用户名密码错误次数超过配置文件中的次数则锁定系统
         */
        count = getUserCount();//获取剩余登录次数
        System.out.println("请输入登录的用户名和密码");
        boolean success;
        while (true) {
            System.out.println("用户名:");
            String username = sc.next();
            System.out.println("密码:");
            String password = sc.next();

            //对录入的用户名密码进行判断
            success = userService.login(username, password);
            if (success) {
                System.out.println("登录成功,即将进入管理系统");
                logger.info("用户 "+username+" 登录了系统");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //登录成功就重置标记和剩余登录次数
                storeProp(Integer.parseInt(max), "true");
                currentUser = getUser(username);  //记录当前的用户名
                welcome();
            } else {
                count--;
                if (count == 0) {
                    System.out.println("您需要冷静一下,请20分钟后再尝试");
                    storeProp(count, "false");
                    //退回登录界面
                    entry();
                }

                //每次输错都记录剩余次数,记录错误时间
                storeProp(count, "false");
                System.out.println("用户名和密码不正确");
                System.out.println("错误" + (count) + "次后你将无法登录");
            }
        }
    }


    //管理员验证
    public boolean isAdmin() {
        String emailMess = null;
        String superEmail = propSuper.getProperty("email");
        String[] split = superEmail.split("@");
        String maskEmail = split[0].substring(0, 2) + "********@" + split[1];
        System.out.println("正在向管理员" + maskEmail + "发送验证码,请稍等...");
        try {

            emailMess = SendEmail.sendEmail(superEmail);//向超级管理员发送验证码
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


        System.out.println("已向管理员邮箱(" + maskEmail + ")发送验证码,请登录管理员邮箱提取或联系管理员索取,并输入验证:");
        int count = 0;
        while (true) {
            if (sc.next().equals(emailMess)) {
                return true;
            } else {
                count++;
                if (count == 3) {
                    System.out.println("验证失败,再见!");
                    return false;
                }
                System.out.println("秘钥不正确,还可以输入" + (3 - count) + "次请重新输入:");
            }
        }
    }

    /*
    @注册时录入用户名密码
    @注册的用户名 邮箱必须唯一
     */
    public void register() {
        loop:
        while (true) {
            System.out.println("请输入用户名");
            String username = sc.next();

            String password1;
            //对两次密码一致性进行判断
            while (true) {
                System.out.println("请第一次输入密码:");
                password1 = sc.next();
                System.out.println("请再次输入密码:");
                String password2 = sc.next();
                if (password1.equals(password2)) {
                    break;
                } else {
                    System.out.println("两次密码不一致");
                }
            }
            System.out.println("请输入手机号");
            String phone = sc.next();

            //管理员验证
            if (!isAdmin()) {
                //验证失败3次退回登录界面
                entry();
            }

            System.out.println("请输入您的注册邮箱,请务必保证邮箱正确,以便接收验证码!后期密码遗忘时将作为唯一找回密码方式!!!");
            String email = sc.next();
            System.out.println("已向您的邮箱发送了验证码,请输入验证码:");
            String randomNumber = null;
            try {
                randomNumber = SendEmail.sendEmail(email);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //对邮箱验证码进行验证
            if (!emailVerify(randomNumber)) {
                entry();//验证失败3次,跳转到登录界面
            }

            UserInfo userInfo = new UserInfo(username, password1, email, phone, LocalDateTime.now());

            //将username password1 传到 service
            boolean success2 = userService.register(userInfo);

            if (success2) {
                System.out.println("注册成功");//转入登录界面
                logger.info("用户 " + username + " 注册成功");
                System.out.println("即将进入登录界面");
                try {
                    Thread.sleep(2000);
                    entry();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                break loop;
            } else {
                System.out.println("用户名已存在,请直接登录");
                while (true) {
                    System.out.println("1 继续注册   2 找回密码 3 返回首页");
                    switch (sc.next()) {
                        case "1":
                            continue loop;
                        case "2":
                            System.out.println("即将进入找回密码页面");
                            findPassword();
                            break;
                        case "3":
                            entry();
                        default:
                            System.out.println("输入有误");
                            break;
                    }
                }
            }
        }
    }


    /*
    @这个方法是对发送的验证码进行判断,3次机会
     */
    private boolean emailVerify(String randomNumber) {
        int countEmail = 0;
        while (true) {
            if (sc.next().equals(randomNumber)) {
                return true;
            } else {
                countEmail++;
                if (countEmail == 3) {
                    System.out.println("输入错误次数过多,再见");
                    return false;
                }

                System.out.println("您输入的验证码不正确,剩余" + (3 - countEmail) + "次,请重新输入:");

            }
        }
    }
        /*
        @通过用户的注册邮箱让用户重设密码
         */
    @Override
    public void findPassword() {
        String username;
        while (true) {
            //用户名存在验证
            System.out.println("请输入用户名");
            username = sc.next();
            if (!userService.isUserExist(username)) {
                System.out.println("用户名不存在");
                return;
            } else {
                break;
            }
        }
        String email;
        while (true) {
            //用户邮箱验证
            System.out.println("请输入用户邮箱");
            email = sc.next();
            //验证码
            if (userService.isEmailExist(email)) {
                break;
            } else {
                System.out.println("邮箱不正确,请重新输入");
            }
        }
        System.out.println("请登录邮箱查看验证码,输入验证码完成验证:");
        String randomNumber = null;
        try {
            randomNumber = SendEmail.sendEmail(email);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //对邮箱验证码进行验证
        if (!emailVerify(randomNumber)) {
            entry();//验证失败3次,跳转到登录界面
        }
        //录入新密码
        System.out.println("请输入新的密码");
        String password1 = sc.next();
        System.out.println("请输入新的密码");
        String password2 = sc.next();

        if (!password1.equals(password2)) {
            System.out.println("两次输入的密码不一致,请重新输入");
        } else {

        }

        userService.ChangePassword(username, password1);
        System.out.println("密码修改成功!");
        System.out.println("即将进入登录页面,请用新密码登录");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        entry();
    }

    /*
    @用户在登录状态时,可以验证原始密码后直接修改密码
     */
    @Override
    public void ChangePassword() {

        System.out.println("请输入原始密码:");
        String oldPassword = sc.next();
        boolean correct = userService.isCorrect(currentUser.getUsername(), oldPassword);
        if (!correct) {
            System.out.println("密码不正确");
            return;
        }
        String newPassword1;
        String newPassword2;
        while (true) {
            System.out.println("请设置新密码:");
            newPassword1 = sc.next();
            System.out.println("请再次输入新密码:");
            newPassword2 = sc.next();
            if (newPassword1.equals(newPassword2)) {
                break;
            }
        }
        userService.ChangePassword(currentUser.getUsername(), newPassword1);
        System.out.println("修改成功,请用新密码重新登录");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        entry();//跳转到登录口


    }



    /*
    用户登录后,通过用户名,从后台返回用户对象
     */
    @Override
    public UserInfo getUser(String username) {

        return userService.getUser(username);
    }


    /*
    @将学生系统中的信息导出到本地Excel表格中
     */
    @Override
    public void importInfo() {


        System.out.println("请将需要导入的文件放到D:\\heima_system\\import 中,并输入文件名:");

        File file = new File("D:\\heima_system\\import", sc.next());
        if (!file.exists()) {
            System.out.println("找不到文件!");
            return;
        }
        long s = System.currentTimeMillis();
        boolean b = userService.importInfo(file);
        long e = System.currentTimeMillis();
        if (b) {
            System.out.println("信息导入成功,总共耗时(单位:毫秒):" + (e - s));
        } else {
            System.out.println("信息导入失败");
        }


    }
    /*
    @将本地Excel表中的数据导入到系统中
     */
    @Override
    public void exportInfo() {
        long s = System.currentTimeMillis();
        boolean b = userService.exportInfo(currentUser.getUsername());
        long e = System.currentTimeMillis();
        if (b) {
//            currentUser.getExportDateList().add(LocalDateTime.now());
            logger.warn("用户 :  " + currentUser.getUsername() + "  导出了学生信息");
            System.out.println("信息导出成功到 D:/heima_system/export 路径中,总共耗时(单位:毫秒):" + (e - s));

        } else {
            System.out.println("暂无数据");
        }
    }




    //获取上次账号密码输入失败的时间和当前的时间差(单位 :秒)
    private long timeAccess() {
        return Duration.between(LocalDateTime.parse((String) propUser.get("time"), fmtProp), LocalDateTime.now()).getSeconds();
    }

    //剩余登录次数判断
    private int getUserCount() {
        return Integer.parseInt((String) propUser.get("count"));
    }


    //获取登录标记
    private boolean getAccess() {
        if ("true".equals((String) propUser.get("access"))) {
            return true;
        }
        return false;
    }

    //储存用户登录失败的信息到配置文件中
    private void storeProp(int count, String access) {
        propUser.setProperty("access", access);
        propUser.setProperty("count", String.valueOf(count));
        propUser.setProperty("time", LocalDateTime.now().format(fmtProp));


        try {
            propUser.store(new FileWriter("D:\\heima_system\\prop\\userAccess.properties", Charset.forName("gbk")), null);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
